#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
性能监控和详细日志记录系统
用于追踪从端侧请求到最终响应的完整链路
"""

import time
import json
import uuid
from datetime import datetime
from typing import Dict, Any, Optional, List
from contextlib import contextmanager
from functools import wraps
import threading
from utils.logger import emobot_logger

logger = emobot_logger.get_logger()


class PerformanceTracker:
    """性能追踪器，用于记录详细的执行时间和调用链路"""

    def __init__(self):
        self._local = threading.local()

    def start_request(self, request_id: str = None, user_id: str = None, session_id: str = None) -> str:
        """开始一个新的请求追踪"""
        if request_id is None:
            request_id = str(uuid.uuid4())

        self._local.request_id = request_id
        self._local.user_id = user_id
        self._local.session_id = session_id
        self._local.start_time = time.time()
        self._local.steps = []
        self._local.current_step = None

        # 记录请求开始
        self._log_step("REQUEST_START", {
            "request_id": request_id,
            "user_id": user_id,
            "session_id": session_id,
            "timestamp": datetime.now().isoformat()
        })

        return request_id

    def start_step(self, step_name: str, step_data: Dict[str, Any] = None) -> str:
        """开始一个新的步骤追踪"""
        step_id = str(uuid.uuid4())
        step_start_time = time.time()

        self._local.current_step = {
            "step_id": step_id,
            "step_name": step_name,
            "start_time": step_start_time,
            "data": step_data or {}
        }

        # 记录步骤开始
        self._log_step("STEP_START", {
            "step_id": step_id,
            "step_name": step_name,
            "data": step_data or {},
            "timestamp": datetime.now().isoformat()
        })

        return step_id

    def end_step(self, step_id: str = None, result_data: Dict[str, Any] = None, error: str = None):
        """结束当前步骤追踪"""
        if self._local.current_step is None:
            logger.warning("No current step to end")
            return

        current_step = self._local.current_step
        if step_id and current_step["step_id"] != step_id:
            logger.warning(f"Step ID mismatch: expected {current_step['step_id']}, got {step_id}")

        end_time = time.time()
        duration = (end_time - current_step["start_time"]) * 1000  # 转换为毫秒

        # 更新步骤信息
        current_step["end_time"] = end_time
        current_step["duration_ms"] = duration
        current_step["result_data"] = result_data or {}
        current_step["error"] = error

        # 添加到步骤列表
        self._local.steps.append(current_step.copy())

        # 记录步骤结束
        self._log_step("STEP_END", {
            "step_id": current_step["step_id"],
            "step_name": current_step["step_name"],
            "duration_ms": duration,
            "result_data": result_data or {},
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

        # 清除当前步骤
        self._local.current_step = None

    def log_api_call(self, api_name: str, api_type: str, request_data: Dict[str, Any] = None,
                     response_data: Dict[str, Any] = None, duration_ms: float = None, error: str = None):
        """记录API调用详情"""
        self._log_step("API_CALL", {
            "api_name": api_name,
            "api_type": api_type,  # VLM, LLM, FACE_RECOGNITION, etc.
            "request_data": request_data or {},
            "response_data": response_data or {},
            "duration_ms": duration_ms,
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

    def log_data_transfer(self, transfer_type: str, data_size: int, duration_ms: float = None,
                          source: str = None, destination: str = None, error: str = None):
        """记录数据传输详情"""
        self._log_step("DATA_TRANSFER", {
            "transfer_type": transfer_type,  # UPLOAD_LOCAL, DOWNLOAD_IMAGE, etc. (OBS已注释)
            "data_size_bytes": data_size,
            "duration_ms": duration_ms,
            "source": source,
            "destination": destination,
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

    def log_database_operation(self, operation: str, table: str, duration_ms: float = None,
                               record_count: int = None, error: str = None):
        """记录数据库操作详情"""
        self._log_step("DATABASE_OPERATION", {
            "operation": operation,  # SELECT, INSERT, UPDATE, DELETE
            "table": table,
            "duration_ms": duration_ms,
            "record_count": record_count,
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

    def log_cache_operation(self, operation: str, key: str, hit: bool = None,
                            duration_ms: float = None, error: str = None):
        """记录缓存操作详情"""
        self._log_step("CACHE_OPERATION", {
            "operation": operation,  # GET, SET, DELETE
            "key": key,
            "hit": hit,
            "duration_ms": duration_ms,
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

    def end_request(self, response_data: Dict[str, Any] = None, error: str = None):
        """结束请求追踪"""
        if not hasattr(self._local, 'start_time'):
            logger.warning("No request to end")
            return

        end_time = time.time()
        total_duration = (end_time - self._local.start_time) * 1000

        # 计算各步骤的统计信息
        step_stats = self._calculate_step_stats()

        # 记录请求结束
        self._log_step("REQUEST_END", {
            "request_id": getattr(self._local, 'request_id', 'unknown'),
            "user_id": getattr(self._local, 'user_id', None),
            "session_id": getattr(self._local, 'session_id', None),
            "total_duration_ms": total_duration,
            "step_count": len(self._local.steps),
            "step_stats": step_stats,
            "response_data": response_data or {},
            "error": error,
            "timestamp": datetime.now().isoformat()
        })

        # 生成性能报告
        self._generate_performance_report(total_duration, step_stats)

    def _log_step(self, step_type: str, data: Dict[str, Any]):
        """记录步骤日志"""
        log_data = {
            "request_id": getattr(self._local, 'request_id', 'unknown'),
            "user_id": getattr(self._local, 'user_id', None),
            "session_id": getattr(self._local, 'session_id', None),
            "step_type": step_type,
            **data
        }

        logger.info(f"PERFORMANCE_TRACK: {json.dumps(log_data, ensure_ascii=False)}")

    def _calculate_step_stats(self) -> Dict[str, Any]:
        """计算步骤统计信息"""
        if not self._local.steps:
            return {}

        # 按步骤类型分组统计
        step_types = {}
        total_api_calls = 0
        total_api_duration = 0
        total_data_transfer = 0
        total_db_operations = 0
        total_db_duration = 0

        for step in self._local.steps:
            step_name = step["step_name"]
            duration = step.get("duration_ms", 0)

            if step_name not in step_types:
                step_types[step_name] = {"count": 0, "total_duration": 0}

            step_types[step_name]["count"] += 1
            step_types[step_name]["total_duration"] += duration

            # 统计特定类型的操作
            if "API_CALL" in step_name:
                total_api_calls += 1
                total_api_duration += duration
            elif "DATA_TRANSFER" in step_name:
                total_data_transfer += duration
            elif "DATABASE" in step_name:
                total_db_operations += 1
                total_db_duration += duration

        return {
            "step_types": step_types,
            "api_calls": {
                "count": total_api_calls,
                "total_duration_ms": total_api_duration,
                "avg_duration_ms": total_api_duration / total_api_calls if total_api_calls > 0 else 0
            },
            "data_transfer": {
                "total_duration_ms": total_data_transfer
            },
            "database_operations": {
                "count": total_db_operations,
                "total_duration_ms": total_db_duration,
                "avg_duration_ms": total_db_duration / total_db_operations if total_db_operations > 0 else 0
            }
        }

    def _generate_performance_report(self, total_duration: float, step_stats: Dict[str, Any]):
        """生成性能报告"""
        report = {
            "request_id": getattr(self._local, 'request_id', 'unknown'),
            "user_id": getattr(self._local, 'user_id', None),
            "session_id": getattr(self._local, 'session_id', None),
            "total_duration_ms": total_duration,
            "performance_summary": step_stats,
            "timestamp": datetime.now().isoformat()
        }

        # 记录性能报告
        logger.info(f"PERFORMANCE_REPORT: {json.dumps(report, ensure_ascii=False)}")

        # 如果总时间超过阈值，记录警告
        if total_duration > 10000:  # 10秒
            logger.warning(f"SLOW_REQUEST: Request {self._local.request_id} took {total_duration:.2f}ms")

        # 如果API调用时间过长，记录警告
        api_stats = step_stats.get("api_calls", {})
        if api_stats.get("avg_duration_ms", 0) > 5000:  # 5秒
            logger.warning(f"SLOW_API_CALLS: Average API call duration {api_stats['avg_duration_ms']:.2f}ms")


# 全局性能追踪器实例
performance_tracker = PerformanceTracker()


def track_performance(step_name: str = None):
    """装饰器：自动追踪函数执行性能"""

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if step_name:
                step_id = performance_tracker.start_step(step_name, {
                    "function": func.__name__,
                    "args_count": len(args),
                    "kwargs_keys": list(kwargs.keys())
                })

            start_time = time.time()
            try:
                result = func(*args, **kwargs)
                duration = (time.time() - start_time) * 1000

                if step_name:
                    performance_tracker.end_step(step_id, {
                        "result_type": type(result).__name__,
                        "success": True
                    })

                return result
            except Exception as e:
                duration = (time.time() - start_time) * 1000

                if step_name:
                    performance_tracker.end_step(step_id, error=str(e))

                raise

        return wrapper

    return decorator


@contextmanager
def track_step(step_name: str, step_data: Dict[str, Any] = None):
    """上下文管理器：追踪代码块执行"""
    try:
        step_id = performance_tracker.start_step(step_name, step_data)
        yield step_id
        performance_tracker.end_step(step_id, {"success": True})
    except AttributeError as e:
        # 如果线程本地存储没有正确初始化，跳过性能跟踪
        logger.warning(f"Performance tracking skipped due to thread-local issue: {e}")
        yield "skipped"
    except Exception as e:
        try:
            performance_tracker.end_step(step_id, error=str(e))
        except:
            pass
        raise


def log_api_call(api_name: str, api_type: str, request_data: Dict[str, Any] = None,
                 response_data: Dict[str, Any] = None, duration_ms: float = None, error: str = None):
    """记录API调用"""
    try:
        performance_tracker.log_api_call(api_name, api_type, request_data, response_data, duration_ms, error)
    except AttributeError as e:
        # 如果线程本地存储没有正确初始化，跳过性能跟踪
        logger.warning(f"API call logging skipped due to thread-local issue: {e}")
    except Exception as e:
        logger.warning(f"API call logging failed: {e}")


def log_data_transfer(transfer_type: str, data_size: int, duration_ms: float = None,
                      source: str = None, destination: str = None, error: str = None):
    """记录数据传输"""
    performance_tracker.log_data_transfer(transfer_type, data_size, duration_ms, source, destination, error)


def log_database_operation(operation: str, table: str, duration_ms: float = None,
                           record_count: int = None, error: str = None):
    """记录数据库操作"""
    performance_tracker.log_database_operation(operation, table, duration_ms, record_count, error)


def log_cache_operation(operation: str, key: str, hit: bool = None,
                        duration_ms: float = None, error: str = None):
    """记录缓存操作"""
    performance_tracker.log_cache_operation(operation, key, hit, duration_ms, error)
